import React, { useCallback, useMemo } from 'react';
import { createEditor } from 'slate';
import { Slate, Editable, withReact } from 'slate-react';
import type { RenderElementProps, RenderLeafProps } from 'slate-react';
import type { EditorMode, FormulaFormatOptions } from '../../types';
import { KaTeXRenderer } from '../../core/renderer/KaTeXRenderer';
import './VisualEditor.css';

interface VisualEditorProps {
  latex: string;
  mode: EditorMode;
  formatOptions: FormulaFormatOptions;
  onLatexChange: (latex: string) => void;
  onCursorChange?: () => void;
}

// Slate编辑器的元素类型定义
type CustomElement = {
  type?: string;
  children: CustomText[];
  inline?: boolean;
};

type CustomText = {
  text: string;
  math?: boolean;
  formula?: string;
};

declare module 'slate' {
  interface CustomTypes {
    Editor: any;
    Element: CustomElement;
    Text: CustomText;
  }
}

/**
 * 可视化编辑器组件 - 使用Slate.js实现公式的可视化编辑
 */
export const VisualEditor: React.FC<VisualEditorProps> = ({
  latex,
  mode,
  formatOptions,
  onLatexChange
}) => {
  // 创建渲染器实例
  const renderer = useMemo(() => new KaTeXRenderer(), []);

  // 将LaTeX转换为Slate文档结构
  const parseLatexToSlate = useCallback((latexString: string) => {
    // 这是一个简化的解析器，实际应用中需要更复杂的解析逻辑
    // 这里我们假设整个内容就是一个公式
    if (!latexString.trim()) {
      return [{ type: 'paragraph', children: [{ text: '' }] }];
    }

    // 检测是否包含公式分隔符
    if (latexString.includes('$')) {
      // 简单处理行内公式和块公式
      const parts = latexString.split(/\$(\$)?/);
      const result = [];
      
      for (let i = 0; i < parts.length; i++) {
        const part = parts[i];
        if (!part.trim()) continue;
        
        // 检查是否为公式部分
        const isFormula = i > 0 && (parts[i-1].endsWith('$') || i === 1);
        
        if (isFormula) {
          result.push({
            type: 'math',
            inline: !parts[i-1].includes('$$'),
            children: [{ text: part, math: true, formula: part }]
          });
        } else {
          result.push({
            type: 'text',
            children: [{ text: part }]
          });
        }
      }
      
      return result.length > 0 ? result : [{ type: 'paragraph', children: [{ text: latexString }] }];
    }
    
    // 如果没有公式分隔符，假设整个内容就是一个公式
    return [{
      type: 'math',
      inline: false,
      children: [{ text: latexString, math: true, formula: latexString }]
    }];
  }, []);

  // 将Slate文档转换回LaTeX
  const serializeSlateToLatex = useCallback((nodes: any[]): string => {
    return nodes.map((node: any): string => {
      if (node.type === 'math') {
        const delimiter = node.inline ? '$' : '$$';
        return delimiter + node.children[0].text + delimiter;
      }
      
      if (node.children) {
        return serializeSlateToLatex(node.children);
      }
      
      return node.text;
    }).join('');
  }, []);

  // 创建编辑器实例
  const editor = useMemo(() => withReact(createEditor()), []);

  // 初始值
  const initialValue = useMemo(() => parseLatexToSlate(latex), [latex, parseLatexToSlate]);

  // 处理文档变化
  const handleChange = useCallback((value: any[]) => {
    const newLatex = serializeSlateToLatex(value);
    onLatexChange(newLatex);
  }, [serializeSlateToLatex, onLatexChange]);

  // 渲染元素
  const renderElement = useCallback((props: RenderElementProps) => {
    const { attributes, children, element } = props;
    
    if (element.type === 'math') {
      const formula = element.children[0]?.formula || '';
      const className = element.inline ? 'inline-math' : 'block-math';
      
      try {
        // 使用KaTeX渲染公式
        const { html: renderedHtml } = KaTeXRenderer.renderToHtml(formula, {
          displayMode: !element.inline,
          throwOnError: false,
          ...formatOptions
        });
        
        return (
          <div
            {...attributes}
            className={`math-element ${className}`}
            dangerouslySetInnerHTML={{ __html: renderedHtml }}
          />
        );
      } catch (error) {
        // 渲染失败时显示原始公式
        return (
          <div {...attributes} className={`math-element ${className} math-error`}>
            {formula}
          </div>
        );
      }
    }
    
    return <p {...attributes}>{children}</p>;
  }, [renderer, formatOptions]);

  // 渲染文本节点
  const renderLeaf = useCallback((props: RenderLeafProps) => {
    const { attributes, children, leaf } = props;
    
    if (leaf.math && leaf.formula) {
      return (
        <span {...attributes} className="math-text">
          {children}
        </span>
      );
    }
    
    return <span {...attributes}>{children}</span>;
  }, []);

  // 插入公式
  // 移除未使用的insertFormula函数

  if (mode !== 'visual') {
    return null;
  }

  return (
    <div className="visual-editor-container">
      <Slate
        editor={editor}
        initialValue={initialValue}
        onChange={handleChange}
      >
        <div className="visual-editor-toolbar">
          <span className="toolbar-label">可视化编辑模式</span>
        </div>
        <Editable
          className="visual-editor"
          renderElement={renderElement}
          renderLeaf={renderLeaf}
          placeholder="在此输入或编辑公式..."
          spellCheck={false}
          autoComplete="off"
          autoCorrect="off"
          autoCapitalize="off"
        />
      </Slate>
    </div>
  );
};

export default VisualEditor;